package net.flyinggroup.scs.gitter.controller;

import net.flyinggroup.scs.gitter.controller.vm.MessageVM;
import net.flyinggroup.scs.gitter.controller.vm.UsersStatisticVM;
import net.flyinggroup.scs.gitter.service.gitter.dto.MessageResponse;
import net.flyinggroup.scs.gitter.service.impl.DefaultStatisticService;
import net.flyinggroup.scs.gitter.service.impl.utils.MessageMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.ReplayProcessor;
import reactor.util.function.Tuple2;

import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Function;

@RestController
@RequestMapping("/api/v1/info")
@SpringBootApplication(exclude = {MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class})
public class InfoResource {
    private final ReplayProcessor<UsersStatisticVM> statisticStream = ReplayProcessor.cacheLast();
    private final ReplayProcessor<MessageVM> messageStream = ReplayProcessor.create(50);

    @Bean
    public Function<Tuple2<Flux<MessageResponse>, Flux<UsersStatisticVM>>, Mono<Void>> listen() {
        return tuple -> {
            Flux<MessageResponse> messages = tuple.getT1();
            Flux<UsersStatisticVM> statistic = tuple.getT2();
            messages.map(MessageMapper::toViewModelUnit).subscribeWith(messageStream);
            statistic.subscribeWith(statisticStream);
            return Mono.empty();
        };
    }

    @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<?> stream() {
        return Flux.merge(messageStream, statisticStream);
    }

    public static void main(String[] args) {
        String[] newArgs = Arrays.copyOf(args, args.length + 1);
        newArgs[args.length] = "--spring.profiles.active=ui";

        ApplicationContext context = SpringApplication.run(InfoResource.class, newArgs);
    }
}
